﻿namespace CompanyPayRollSystem.BusinessLayer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using CompanyPayRollSystem.Database;
    using CompanyPayRollSystem.Utilities;

    /// <summary>
    /// Manager for EmployeeSalaryItems table
    /// </summary>
    public class EmployeeSalaryItemsManager : EntityManager
    {
        /// <summary>
        /// Calculates the employee salary.
        /// </summary>
        /// <param name="employeeSalaryItem">The employee salary item.</param>
        /// <returns>Gross Salary</returns>
        public static double CalculateEmployeeSalary(EmployeeSalaryItem employeeSalaryItem)
        {
            try
            {
                // TODO: calculate the employee basic salary + Incentives Percentage + bonus Percentage for the given month and year
                double total = employeeSalaryItem.Employee.Salary + (employeeSalaryItem.Bonus * employeeSalaryItem.Employee.Salary);
                return total;
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Marks as delivered.
        /// </summary>
        /// <param name="employeeSalaryItem">The employee salary item.</param>
        /// <param name="dateTime">The date time.</param>
        public static void MarkAsDelivered(EmployeeSalaryItem employeeSalaryItem, DateTime dateTime)
        {
            try
            {
                employeeSalaryItem.IsDelivered = true;
                employeeSalaryItem.DeliveryDate = dateTime;
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Gets the employee salary items.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <returns>returns the salary item of the specified employee in the specified month and year.</returns>
        public static EmployeeSalaryItem GetEmployeeSalaryItems(int employeeID, int month, int year)
        {
            try
            {
                EmployeeSalaryItem[] employeeSalaryItems = Context.EmployeeSalaryItems.Where(salaryItem => salaryItem.EmployeeID == employeeID && salaryItem.Month == month && salaryItem.Year == year).ToArray();
                if (employeeSalaryItems.Length != 1)
                {
                    return null;
                }
                else
                {
                    return employeeSalaryItems[0];
                }
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Updates the employee salary items without saving.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveEmployeeSalaryItems(int employeeID, int month, int year, double bonusPercentage)
        {
            try
            {
                bool addedSuccessfully = true;
                addedSuccessfully = UpdateEmployeeSalaryItems(employeeID, month, year, bonusPercentage);
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Saves the department salary items.
        /// </summary>
        /// <param name="departmentID">The department ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveDepartmentSalaryItems(int departmentID, int month, int year, double bonusPercentage)
        {
            // TODO: Set the employee Incentives and bonus for the given month and year for all employees in given department
            List<Employee> employees = EmployeeManager.GetEmployees(departmentID);
            foreach (Employee employee in employees)
            {
                UpdateEmployeeSalaryItems(employee.EmployeeID, month, year, bonusPercentage);
            }

            try
            {
                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Saves all employees salary items.
        /// </summary>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        public static void SaveAllEmployeesSalaryItems(int month, int year, double bonusPercentage)
        {
            try
            {
                List<Employee> employees = EmployeeManager.GetEmployees();
                foreach (Employee employee in employees)
                {
                    UpdateEmployeeSalaryItems(employee.EmployeeID, month, year, bonusPercentage);
                }

                Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Updates the employee salary items.
        /// </summary>
        /// <param name="employeeID">The employee ID.</param>
        /// <param name="month">The month.</param>
        /// <param name="year">The year.</param>
        /// <param name="bonusPercentage">The bonus percentage.</param>
        /// <returns>
        /// True if the Salary Item was not delivered already.
        /// </returns>
        private static bool UpdateEmployeeSalaryItems(int employeeID, int month, int year, double bonusPercentage)
        {
            try
            {
                bool alreadyExisting = true;
                EmployeeSalaryItem employeeSalaryItem = GetEmployeeSalaryItems(employeeID, month, year);
                if (employeeSalaryItem == null)
                {
                    employeeSalaryItem = new EmployeeSalaryItem();
                    employeeSalaryItem.EmployeeID = employeeID;
                    employeeSalaryItem.Month = month;
                    employeeSalaryItem.Year = year;
                    employeeSalaryItem.IsDelivered = false;
                    alreadyExisting = false;
                }
                else if (employeeSalaryItem.IsDelivered)
                {
                    // salary cashed out already-> cannot be modified
                    return false;
                }

                employeeSalaryItem.Bonus = bonusPercentage;

                if (!alreadyExisting)
                {
                    Context.EmployeeSalaryItems.InsertOnSubmit(employeeSalaryItem);
                }

                return true;
            }
            catch (Exception ex)
            {
                // Log Exception
                Utilities.Logger.LogException(ex);
                throw ex;
            }
        }
    }
}